package com.fuyun.microservice.proxy;


import com.fuyun.microservice.ResultObject;
import com.fuyun.microservice.gate.model.rule.ZuulRouteInfo;
import com.fuyun.microservice.proxy.client.RuleClient;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.PathMatcher;

import java.util.List;


@Slf4j
public class DefaultForwardRoute implements DiscoveryRoute {
    private static final  List<ZuulRouteInfo> LOCAL_ROUTES = Lists.newArrayList();

    private PathMatcher pathMatcher = new AntPathMatcher();

    @Autowired
    RuleClient ruleClient;

    @Scheduled(cron = "0/30 * * * * ?")
    public synchronized void refreshRouteJob() {
        log.debug("sync local cache...");
        ResultObject<List<ZuulRouteInfo>> routeResult = ruleClient.routes();
        if (routeResult.isSuccess()) {
            LOCAL_ROUTES.clear();
            LOCAL_ROUTES.addAll(routeResult.getData());
        }
    }

    @Override
    public ForwardRoute match(String uri) {
        ZuulRouteInfo matchingRoute = getMatchingRoute(uri);

        if (matchingRoute != null) {
            ForwardRoute forwardRoute = new ForwardRoute();
            forwardRoute.setServiceId(matchingRoute.getServiceId());
            forwardRoute.setServiceUri(getTargetPath(matchingRoute, uri));
            return forwardRoute;
        }

        return null;
    }


    private ZuulRouteInfo getMatchingRoute(String path) {
        for (ZuulRouteInfo routeInfo : LOCAL_ROUTES) {
            if (pathMatcher.match(routeInfo.getPath(), path)) {
                return routeInfo;
            }
        }
        return null;
    }

    protected String getTargetPath(ZuulRouteInfo route, String path) {
        String targetPath = path;
        int index = route.getPath().indexOf("*") - 1;
        if (index > 0) {
            String routePrefix = route.getPath().substring(0, index);
            targetPath = targetPath.replaceFirst(routePrefix, "");
        }

        return targetPath;
    }
}
